#ifndef __C_ARCH_SYS_H__
#define __C_ARCH_SYS_H__

#include "std/std.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct thread_arch_data
{
	uint esp;
	uint eip;
}
thread_arch_data_t;

#define init_thread_arch_data(data, stkptr, entry)	\
do { \
	data.esp = (uint)(stkptr); \
	data.eip = (uint)(entry); \
} while (0)

#ifdef TEST_DBG_WIN32
#define __reg2
#else
#define __reg2 __attribute__((regparm(2)))
#endif

void __reg2 _switch_to(thread_arch_data_t* prev, thread_arch_data_t* next);

// arch specific thread switch
#define thread_switch_to(prev, next)	\
do { \
	asm volatile( \
	"push %%fs			\n\t" \
	"push %%gs			\n\t" \
	"push %%esi			\n\t" \
	"push %%edi			\n\t" \
	"push %%ebp			\n\t" \
	"pushf				\n\t" \
	"cli				\n\t" \
	"movl %%esp,%0		\n\t" /* save esp */ \
	"movl %2,%%esp		\n\t" /* restore esp */ \
	"movl $1f,%1		\n\t" /* save eip */ \
	"pushl %3			\n\t" \
	"sti				\n\t" \
	"jmp __switch_to	\n\t" \
	"1:					\n\t" \
	"popf				\n\t" \
	"pop %%ebp			\n\t" \
	"pop %%edi			\n\t" \
	"pop %%esi			\n\t" \
	"pop %%gs			\n\t" \
	"pop %%fs			\n\t" \
	"\n\t" \
	:"=m" ((prev)->esp),"=m" ((prev)->eip)	\
	:"m" ((next)->esp),"m" ((next)->eip),	\
	"a"(prev), "d"(next));		\
} while (0)

#ifdef __cplusplus
}
#endif
#endif
/* EOF */
